• 任务是一组逻辑工作单元,而线程则是使任务异步执行的机制

  • Executor提供了一种标准的方法将任务的提交过程和执行过程解耦开来,并用Runnable表示任务,Executor基于生产者-消费者模式,提交任务的操作相当于生产者(生产待完成的工作单元),执行任务的线程则相当于消费者(执行完这些工作单元)。

    如果要在程序中实现一个生产者-消费者的设计,那么最简单的方式就是使用Executor

  • 每当看到下面形式的代码时:new Thread(runnable).start(),并且你希望获得一种更灵活的执行策略时,请考虑使用Executor来代替Thread。

  • java.lang.concurrent提供了线程池作为实现executor框架的一部分:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class TaskExecutionWebServer {
    private static final int nTHREADS = 100;
    private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);
    public static void main(String[] args) throws IOException {
    ServerSocket socket = new ServerSocket(80);
    while (true) {
    final Socket connection = socket.accept();
    Runnable task = new Runnable() {
    public void run() {
    handleRequest(connection);
    }
    };
    exec.execute(task);
    }
    }
    private static void handleRequest(Socket connection) {
    }
    }
  • Executor的实现通常会创建线程来执行任务,但JVM只有在所有(非守护)线程全部终止后才会退出,因此,如果无法正确的关闭Executor,那么JVM将无法结束。

  • Executor框架使用Runnable作为其基本的任务表示形式,Runnable是一种有很大局限的抽象,虽然run能写入到日志文件或者将结果放入某个共享的数据结构,但它不能返回一个值或抛出一个受检查的异常。

  • Callable认为主入口点(即call)将返回一个值,并可能抛出一个异常。

  • Future表示一个任务的生命周期,并提供了相应的方法来判断是否已经完成或取消,以及获取任务的结果和取消任务等。get方法的行为取决于任务的状态(尚未开始、正在运行、已完成)。如果任务已经完成,那么get会立即返回或者抛出一个Exception,如果任务没有完成,那么get将阻塞并直到任务完成。如果任务抛出了异常,那么get将该异常封装为ExecutionException并重新抛出。如果任务被取消,那么get将抛出CancellationException,如果get抛出了ExecutionException,那么可以通过getCause()获得被封装的初始异常。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public interface Callable<V> {
    V call() throws Exception;
    }
    public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean inDone();
    V get() throws InterruptedException, ExecutionException, CancellationException;
    v get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, CancellationException, TimeoutException;
    }

    要使用Callable来表示无返回值的任务,可使用Callable<void>